package fox.framework.rpc.context;

import fox.framework.rpc.client.RpcClient;
import fox.framework.rpc.client.invocation.ConsumeInvoker;
import fox.framework.rpc.client.invocation.proxy.RpcProxyFactory;
import fox.framework.rpc.context.aware.RpcApplicationContextAware;
import fox.framework.rpc.context.definition.RpcDefinition;
import fox.framework.rpc.context.definition.RpcDefinitionBuilder;
import fox.framework.rpc.context.generator.name.RpcNameGenerator;
import fox.framework.rpc.context.order.Order;

import java.util.ArrayList;
import java.util.List;

/**
 * @author cuichao
 * @Description: ConfigurableRegisteredRpcObjectFactory
 * @Date: create in 2021/2/18 1:21
 */
public abstract class ConfigurableRegisteredRpcObjectFactory implements RpcDefinitionRegister,RpcObjectFactory,RpcApplicationContextAware {

    private RpcApplicationContext context;
    /**
     * 代理工厂
     */
    private RpcProxyFactory proxyFactory;
    /**
     * 名称生成器
     */
    private RpcNameGenerator nameGenerator;
    /**
     * 未注册的消费者执行器
     */
    private List<ConsumeInvoker> unRegisteredConsumerInvokers = new ArrayList<>();
    /**
     * 注册过的消费者执行器
     */
    private List<ConsumeInvoker> registeredConsumerInvokers = new ArrayList<>();
    /**
     * RpcClient
     */
    private RpcClient client;



    @Override
    public void setRpcApplicationContext(RpcApplicationContext context) {
        this.context = context;
    }


    private RpcDefinition buildRpcDefinition(Class target, boolean isProvider) {
        RpcDefinitionBuilder builder = RpcDefinitionBuilder.genericRpcDefinition();
        String name = target.getSimpleName();
        builder.setApplicationName(context.name());
        builder.setMetaspace(name);
        builder.setServiceInterface(target);
        builder.setLazy(false);
        builder.setProvider(isProvider);
        builder.setGroup(context.getGlobalGroup());
        return  builder.getDefinition();
    }


    void setRpcClient(RpcClient client){
        this.client = client;
    }

    void setProxyFactory(RpcProxyFactory proxyFactory){
        this.proxyFactory = proxyFactory;
    }

    void setNameGenerator(RpcNameGenerator nameGenerator){
        this.nameGenerator = nameGenerator;
    }

    void setUnRegisteredConsumerInvokers(List<ConsumeInvoker> invokers){
        unRegisteredConsumerInvokers.clear();
        unRegisteredConsumerInvokers.addAll(invokers);
    }

    protected RpcClient getRpcClient(){
        return this.client;
    }

    public RpcProxyFactory getProxyFactory(){
        return this.proxyFactory;
    }

    protected List<ConsumeInvoker> getRegisteredConsumerInvokers(){
        return this.registeredConsumerInvokers;
    }

    void refresh(){
        //注册Rpc客户端方法调用器
        registerRpcConsumeInvoker();
        //init Rpc-Proxy-support
        initProxySupport();
        //交给具体实现容器来实现具体刷新动作
        doRefresh();
    }

    private void registerRpcConsumeInvoker() {
        List<ConsumeInvoker> ordered = new ArrayList<>();
        List<ConsumeInvoker> nonOrdered = new ArrayList<>();
        for (ConsumeInvoker consumeInvoker : unRegisteredConsumerInvokers) {
            if(consumeInvoker instanceof Order){
                ordered.add(consumeInvoker);
            }else {
                nonOrdered.add(consumeInvoker);
            }
        }
        //fill
        Order.sort(ordered);
        registeredConsumerInvokers.clear();
        registeredConsumerInvokers.addAll(ordered);
        registeredConsumerInvokers.addAll(nonOrdered);
        //clear
        unRegisteredConsumerInvokers.clear();
    }


    private void initProxySupport(){
        RpcProxySupport.initRuntimeRpcClient(getRpcClient());
        RpcProxySupport.initRegisteredProxyInvoker(registeredConsumerInvokers);
    }

    /**
     * refresh 刷新容器
     */
    protected abstract void doRefresh();

}
